using System;
using System.Diagnostics;
using System.IO.Ports;
using Utilities;
using Transport.Interfaces;

namespace Transport
{
    internal class SerialPortFullDuplexChannel : IFullDuplexChannel
    {
        private SerialPort _com;

        private object _sendLocker = new object();

        public SerialPortFullDuplexChannel(string ComPort, int BaudRate)
        {
            _com = new SerialPort(ComPort, BaudRate);
        }

        public event ByteArrayEventHandler DataReceived;

        public void Start()
        {
            _com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);

            _com.Open();
        }

        public void Stop()
        {
            _com.DataReceived -= new SerialDataReceivedEventHandler(com_DataReceived);
            _com.Close();
            _com.Dispose();
        }

        public void Reset()
        {
            _com.DiscardInBuffer();
            _com.DiscardOutBuffer();
        }

        public void SendData(byte[] Message)
        {
            lock (_sendLocker)
            {
                _com.Write(Message, 0, Message.Length);
            }
        }

        private void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (e.EventType != SerialData.Chars) return;

            try
            {
                int n = _com.BytesToRead;
                byte[] buf = new byte[n];

                _com.Read(buf, 0, n);

                raiseDataReceivedEvent(buf);
            }
            catch (Exception ex)
            {
                DiagnosticLog.TraceError(ex.ToString());
            }
        }

        private void raiseDataReceivedEvent(byte[] data)
        {
            if (DataReceived != null)
            {
                DataReceived(data);
            }
        }
    }
}